#include "./music_uart.h"
#include "../device/device.h"
#include "../service/device_info.h"
#include "./log_uart.h"

namespace driver {

using namespace service;
utils::Object<MusicUart_t> musicUart;

// PA15 <=> TXD2
// PA16 <=> RXD2
// PA20 <=> BUSY
MusicUart_t::MusicUart_t() {

    GPIO_InitStruType gpio;
    UART_InitStruType uart;

    gpio.GPIO_Signal = GPIO_Pin_Signal_Digital;
    gpio.GPIO_Func = GPIO_Func_2;
    gpio.GPIO_Direction = GPIO_Dir_Out;
    gpio.GPIO_PUEN = GPIO_PUE_Input_Disable;
    gpio.GPIO_PDEN = GPIO_PDE_Input_Disable;
    gpio.GPIO_OD = GPIO_ODE_Output_Disable;
    gpio.GPIO_DS = GPIO_DS_Output_Strong;
    GPIO_Init(GPIOA, GPIO_Pin_15, &gpio);

    gpio.GPIO_Direction = GPIO_Dir_In;
    gpio.GPIO_PUEN = GPIO_PUE_Input_Enable;
    GPIO_Init(GPIOA, GPIO_Pin_16, &gpio);

    gpio.GPIO_Func = GPIO_Func_0;
    GPIO_Init(GPIOA, GPIO_Pin_20, &gpio);

    uart.UART_StopBits = UART_StopBits_1;
    uart.UART_TxMode = UART_DataMode_8;
    uart.UART_TxPolar = UART_Polar_Normal;
    uart.UART_RxMode = UART_DataMode_8;
    uart.UART_RxPolar = UART_Polar_Normal;
    uart.UART_BaudRate = 9600;
    uart.UART_ClockSet = UART_Clock_1;
    UART_Init(UART2, &uart);

    UART_TBIMConfig(UART2, UART_TRBIM_Byte);
    UART_RBIMConfig(UART2, UART_TRBIM_Byte);
    
    UART2_TxEnable();
    UART2_RxEnable();
}

bool MusicUart_t::is_busy() {
    return GPIO_ReadBit(GPIOA, GPIO_Pin_20) == RESET;
}

void MusicUart_t::wait_busy() {
    
    for (;;) {
        osDelay(500);
        if (!is_busy()) {
            return;
        }
    }
}

void MusicUart_t::write_byte(uint8_t byte) {
    while(UART_GetFlagStatus(UART2, UART_FLAG_TB) == RESET);
    UART_SendByte(UART2, byte);
}

void MusicUart_t::play(uint8_t index) {
    
    uint8_t buf[] = {
        0x7E, 0xFF, 0x06, 0x03, 0x00, 0x00, index, 0xEF
    };
    for (uint8_t i = 0; i < sizeof (buf); i ++) {
        write_byte(buf[i]);
    }
    osDelay(100);
    set_volume(deviceInfo->volume);
}

void MusicUart_t::set_volume(uint8_t val) {
    uint8_t buf[] = {
        0x7E, 0xFF, 0x06, 0x06, 0x00, 0x00, val, 0xEF
    };
    for (uint8_t i = 0; i < sizeof (buf); i ++) {
        write_byte(buf[i]);
    }
    if (val == deviceInfo->volume) {
        return;
    }
    deviceInfo->volume = val;
    deviceInfo.save();
}

void MusicUart_t::add_volume() {
    uint32_t val = deviceInfo->volume + 1;
    if (val > 30) {
        return;
    }
    set_volume(val);
}

void MusicUart_t::sub_volume() {
    uint32_t val = deviceInfo->volume;
    if (val <= 0) {
        return;
    }
    set_volume(val - 1);
}

}
